package cn.sdstudio.service.impl;
import cn.sdstudio.model.PageResult;
import cn.sdstudio.entity.GuideScenicRelation;
import cn.sdstudio.entity.TravelGuide;
import cn.sdstudio.dto.TravelGuideDTO;
import cn.sdstudio.vo.ScenicSpotVO;
import cn.sdstudio.vo.TravelGuideVO;
import cn.sdstudio.exception.BusinessException;
import cn.sdstudio.mapper.GuideScenicRelationMapper;
import cn.sdstudio.mapper.ScenicSpotMapper;
import cn.sdstudio.mapper.TravelGuideMapper;
import cn.sdstudio.service.TravelGuideService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class TravelGuideServiceImpl extends ServiceImpl<TravelGuideMapper, TravelGuide> implements TravelGuideService {

    private final TravelGuideMapper travelGuideMapper;
    private final GuideScenicRelationMapper guideScenicRelationMapper;
    private final ScenicSpotMapper scenicSpotMapper;

    @Transactional
    @Override
    public Long createGuide(TravelGuideDTO travelGuideDTO) {
        TravelGuide guide = new TravelGuide();
        guide.setUserId(travelGuideDTO.getUserId())
                .setTitle(travelGuideDTO.getTitle())
                .setContent(travelGuideDTO.getContent())
                .setCoverImage(travelGuideDTO.getCoverImage());

        travelGuideMapper.insert(guide);

        if(travelGuideDTO.getScenicSpotIds() != null) {
            travelGuideDTO.getScenicSpotIds().forEach(scenicId -> {
                GuideScenicRelation guideScenicRelation = new GuideScenicRelation();
                guideScenicRelation.setGuideId(guide.getId());
                guideScenicRelation.setGuideId(scenicId);
                guideScenicRelationMapper.insert(guideScenicRelation);
            });
        }
        return guide.getId();
    }

    @Override
    public TravelGuideVO getTravelGuideVoById(Long id) {
        TravelGuide guide = travelGuideMapper.selectById(id);
        if(guide == null) {
            throw new BusinessException("攻略不存在");
        }

        List<GuideScenicRelation> guideScenicRelations = guideScenicRelationMapper.selectByGuideId(id);
        List<Long> scenicIds = guideScenicRelations.stream()
                .map(GuideScenicRelation::getScenicId)
                .collect(Collectors.toList());

        // 查询景点详细信息
        List<ScenicSpotVO> scenicSpots = scenicSpotMapper.selectBatchIds(scenicIds).stream()
                .map(spot -> new ScenicSpotVO()
                        .setId(spot.getId())
                        .setName(spot.getName())
                        .setCoverImage(spot.getCoverImage()))
                .collect(Collectors.toList());

        TravelGuideVO travelGuideVo = new TravelGuideVO();
        travelGuideVo.setTitle(guide.getTitle())
                .setContent(guide.getContent())
                .setCoverImage(guide.getCoverImage())
                .setId(guide.getId())
                .setUserId(guide.getUserId())
                .setCreateTime(guide.getCreateTime())
                .setScenicSpotIds(scenicIds)
                .setScenicSpots(scenicSpots);
        return travelGuideVo;
    }

    @Override
    public PageResult<TravelGuideVO> listGuides(Integer pageNo, Integer pageSize) {
        Page<TravelGuide> page = new Page<>(pageNo, pageSize);
        IPage<TravelGuide> guidePage = travelGuideMapper.selectPage(page,
                new LambdaQueryWrapper<TravelGuide>()
                        .eq(TravelGuide::getStatus, 1)
                        .orderByDesc(TravelGuide::getCreateTime));

        if (guidePage.getRecords().isEmpty()) {
            return new PageResult<>(Collections.emptyList(),0L);
        }

        // 获取攻略ID集合
        List<Long> guideIds = guidePage.getRecords().stream()
                .map(TravelGuide::getId)
                .collect(Collectors.toList());

        // 批量查询关联关系
        List<GuideScenicRelation> relations = guideScenicRelationMapper.selectList(
                new LambdaQueryWrapper<GuideScenicRelation>()
                        .in(GuideScenicRelation::getGuideId, guideIds));

        // 获取所有景点ID
        List<Long> scenicIds = relations.stream()
                .map(GuideScenicRelation::getScenicId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询景点信息
        Map<Long, ScenicSpotVO> scenicSpotMap = scenicSpotMapper.selectBatchIds(scenicIds).stream()
                .collect(Collectors.toMap(
                        spot -> spot.getId(),
                        spot -> new ScenicSpotVO()
                                .setId(spot.getId())
                                .setName(spot.getName())
                                .setCoverImage(spot.getCoverImage())
                ));

        // 构建攻略ID到景点列表的映射
        Map<Long, List<ScenicSpotVO>> scenicSpotsMap = relations.stream()
                .collect(Collectors.groupingBy(
                        GuideScenicRelation::getGuideId,
                        Collectors.mapping(
                                relation -> scenicSpotMap.get(relation.getScenicId()),
                                Collectors.toList()
                        )
                ));

        // 构建返回结果
        List<TravelGuideVO> list = guidePage.getRecords().stream()
                .map(guide -> new TravelGuideVO()
                        .setId(guide.getId())
                        .setUserId(guide.getUserId())
                        .setTitle(guide.getTitle())
                        .setCoverImage(guide.getCoverImage())
                        .setViewCount(guide.getViewCount())
                        .setCreateTime(guide.getCreateTime())
                        .setScenicSpots(scenicSpotsMap.getOrDefault(guide.getId(), Collections.emptyList())))
                .collect(Collectors.toList());

        return new PageResult<>(list,guidePage.getTotal());
    }

    @Override
    public List<TravelGuideVO> getGuideScenicRelations(Long scenicId) {
        // 查询关联该景点的攻略ID
        List<Long> guideIds = guideScenicRelationMapper.selectList(
                        new LambdaQueryWrapper<GuideScenicRelation>()
                                .eq(GuideScenicRelation::getScenicId, scenicId))
                .stream()
                .map(GuideScenicRelation::getGuideId)
                .collect(Collectors.toList());

        if (guideIds.isEmpty()) {
            return Collections.emptyList();
        }

        // 查询攻略基本信息
        List<TravelGuide> guides = travelGuideMapper.selectList(
                new LambdaQueryWrapper<TravelGuide>()
                        .in(TravelGuide::getId, guideIds)
                        .eq(TravelGuide::getStatus, 1));

        // 查询这些攻略关联的所有景点关系
        List<GuideScenicRelation> relations = guideScenicRelationMapper.selectList(
                new LambdaQueryWrapper<GuideScenicRelation>()
                        .in(GuideScenicRelation::getGuideId, guideIds));

        // 获取所有景点ID
        List<Long> allScenicIds = relations.stream()
                .map(GuideScenicRelation::getScenicId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询景点信息
        Map<Long, ScenicSpotVO> scenicSpotMap = scenicSpotMapper.selectBatchIds(allScenicIds).stream()
                .collect(Collectors.toMap(
                        spot -> spot.getId(),
                        spot -> new ScenicSpotVO()
                                .setId(spot.getId())
                                .setName(spot.getName())
                                .setCoverImage(spot.getCoverImage())
                ));

        // 构建攻略ID到景点列表的映射
        Map<Long, List<ScenicSpotVO>> scenicSpotsMap = relations.stream()
                .collect(Collectors.groupingBy(
                        GuideScenicRelation::getGuideId,
                        Collectors.mapping(
                                relation -> scenicSpotMap.get(relation.getScenicId()),
                                Collectors.toList()
                        )
                ));

        return guides.stream()
                .map(guide -> new TravelGuideVO()
                        .setId(guide.getId())
                        .setUserId(guide.getUserId())
                        .setTitle(guide.getTitle())
                        .setCoverImage(guide.getCoverImage())
                        .setViewCount(guide.getViewCount())
                        .setCreateTime(guide.getCreateTime())
                        .setScenicSpots(scenicSpotsMap.getOrDefault(guide.getId(), Collections.emptyList())))
                .collect(Collectors.toList());
    }
}